package processor

import (
	"fmt"

	"github.com/dop251/goja"
)

// TransformProcessor is a processor that transforms data using JavaScript
type TransformProcessor struct {
	// vm is the JavaScript VM
	vm *goja.Runtime
	// function is the JavaScript function
	function goja.Callable
}

// Init initializes the processor
func (p *TransformProcessor) Init(config map[string]interface{}) error {
	// Get function from config
	functionRaw, ok := config["function"]
	if !ok {
		return fmt.Errorf("function is required")
	}

	functionStr, ok := functionRaw.(string)
	if !ok {
		return fmt.Errorf("function must be a string")
	}

	// Create JavaScript VM
	p.vm = goja.New()

	// Evaluate function
	_, err := p.vm.RunString(functionStr)
	if err != nil {
		return fmt.Errorf("failed to evaluate function: %w", err)
	}

	// Get process function
	processValue := p.vm.Get("process")
	if processValue == nil {
		return fmt.Errorf("process function not found")
	}

	// Convert to callable
	function, ok := goja.AssertFunction(processValue)
	if !ok {
		return fmt.Errorf("process is not a function")
	}

	p.function = function
	return nil
}

// Process processes data
func (p *TransformProcessor) Process(data []byte, metadata map[string]string) ([]byte, error) {
	// Parse data as JSON
	var parsedData interface{}
	err := p.vm.ExportTo(p.vm.ToValue(string(data)), &parsedData)
	if err != nil {
		return nil, fmt.Errorf("failed to parse data: %w", err)
	}

	// Call function
	result, err := p.function(goja.Undefined(), p.vm.ToValue(parsedData))
	if err != nil {
		return nil, fmt.Errorf("failed to call function: %w", err)
	}

	// Convert result to string
	resultStr := result.String()
	if resultStr == "undefined" {
		return nil, fmt.Errorf("function returned undefined")
	}

	return []byte(resultStr), nil
}

// Close closes the processor
func (p *TransformProcessor) Close() error {
	// Nothing to close
	return nil
}

// NewTransformProcessor creates a new transform processor
func NewTransformProcessor() (Processor, error) {
	return &TransformProcessor{}, nil
}

func init() {
	RegisterProcessorFactory("transform", NewTransformProcessor)
}
